﻿#define DDCL_CORE

#include "ddcl.h"

#include "ddclerr.h"
#include "ddclfile.h"
#include "ddclservice.h"
#include "ddcltimer.h"
#include "ddclsocket.h"
#include "ddcllog.h"
#include "ddclmalloc.h"

#include <stdlib.h>
#include <memory.h>

#define CKRETURN(X) { int r = X(); if(r != 0) return r; }

static ddcl g_conf;
static int _INIT = 0;

struct st_Module {
    int id;
    int is_open;
    int (*open_fn)();
    void (*close_fn)();
};
static struct st_Module _M[DDCL_END_MODULE];

static void
set_module (int id, int(*open_fn)(), void(*close_fn)()){
    struct st_Module * m = &(_M[id]);
    m->id = id;
    m->is_open = 0;
    m->open_fn = open_fn;
    m->close_fn = close_fn;
}

static struct st_Module *
get_module (int module){
    if(module <= DDCL_START_MODULE || module >= DDCL_END_MODULE){
        return NULL;
    }
    return &(_M[module]);
}

DDCLAPI int
ddcl_init (ddcl * conf){
    if(_INIT){
        return 0;
    }
    _INIT = 1;
    memset(_M, 0, sizeof(_M));
    g_conf = *conf;
    CKRETURN(ddcl_init_file_module);
    CKRETURN(ddcl_init_timer);

    set_module(DDCL_TIMER_MODULE,
            ddcl_open_timer_module,
            ddcl_close_timer_module);
    set_module(DDCL_SERVICE_MODULE,
            ddcl_open_service_module,
            ddcl_close_service_module);
    set_module(DDCL_SOCKET_MODULE,
            ddcl_open_socket_module,
            ddcl_close_service_module);
    set_module(DDCL_LOG_MODULE,
            ddcl_open_log_module,
            ddcl_close_service_module);

    return 0;
}

DDCLAPI int
ddcl_open (int module){
    if(!_INIT){
        return 0;
    }
    struct st_Module * m = get_module(module);
    if(!m){
        return DDCL_MODULE_NOT_EXIST;
    }
    if(m->is_open){
        return 0;
    }
    CKRETURN(m->open_fn);
    m->is_open = 1;
    return 0;
}

DDCLAPI int
ddcl_open_all (){
    for(int i = DDCL_START_MODULE; i < DDCL_END_MODULE - 1; i ++){
        int err = ddcl_open(i + 1);
        if(err){
            return err;
        }
    }
    return 0;
}

DDCLAPI int
ddcl_is_open (int module){
    struct st_Module * m = get_module(module);
    return m ? m->is_open : 0;
}

DDCLAPI void
ddcl_final (){
    for(int i = DDCL_START_MODULE; i < DDCL_END_MODULE - 1; i ++){
        struct st_Module * m = get_module(i + 1);
        m->close_fn();
    }
}

DDCLAPI void
ddcl_default (ddcl * conf){
    conf->worker = 1;
    conf->socket = 1;
    conf->sleep = 16;
}

DDCLAPI ddcl *
ddcl_conf (){
    return &g_conf;
}
